package com.meida.module.arc.provider.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.meida.common.base.constants.CommonConstants;
import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.service.WebSocketMsgService;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.configuration.OpenCommonProperties;
import com.meida.common.mybatis.base.service.impl.BaseServiceImpl;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaDelete;
import com.meida.common.mybatis.query.CriteriaQuery;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.mybatis.query.CriteriaUpdate;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.ApiAssert;
import com.meida.common.utils.StringUtils;
import com.meida.module.arc.client.constants.ArchiveConstants;
import com.meida.module.arc.client.entity.*;
import com.meida.module.arc.client.enums.ArchiveEnumInteger;
import com.meida.module.arc.client.vo.ArcWaterMarkJson;
import com.meida.module.arc.provider.handler.EsHandler;
import com.meida.module.arc.provider.handler.HookUpHanlder;
import com.meida.module.arc.provider.mapper.ArcOriginalMapper;
import com.meida.module.arc.provider.repository.ArcOriginalRepository;
import com.meida.module.arc.provider.service.*;
import com.meida.module.arc.provider.util.FileConvertUtil;
import com.meida.module.arc.provider.util.FileWaterMarkUtil;
import com.meida.module.file.client.entity.MinioLog;
import com.meida.module.file.client.entity.SysFile;
import com.meida.module.file.client.vo.OssSetting;
import com.meida.module.file.provider.oss.FileUploadUtil;
import com.meida.module.file.provider.oss.client.MioClient;
import com.meida.module.file.provider.service.MinioLogService;
import com.meida.module.file.provider.service.SysFileService;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.LosslessFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.ofdrw.converter.ofdconverter.PDFConverter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 档案原文表接口实现类
 *
 * @author flyme
 * @date 2021-12-05
 */
@Service
@Transactional(rollbackFor = Exception.class)
@DS("sharding")
public class ArcOriginalServiceImpl extends BaseServiceImpl<ArcOriginalMapper, ArcOriginal> implements ArcOriginalService {

    @Autowired
    @Lazy
    private SysFileService sysFileService;

    @Autowired
    @Lazy
    private ArcInfoService arcInfoService;

    @Resource
    private ArcOriginalRepository arcOriginalRepository;

    @Autowired
    private ArcCategoryService arcCategoryService;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private MinioLogService minioLogService;

    @Autowired
    private ArcFieldService arcFieldService;

    @Autowired(required = false)
    private WebSocketMsgService webSocketMsgService;

    @Autowired
    private MioClient mioClient;

    @Autowired
    private HookUpHanlder hookUpHanlder;

    @Autowired
    private SyncService syncService;

    @Value("${meida.uploadFolder:''}")
    private String uploadFolder;

    @Value("${meida.standalone:false}")
    private String standalone;

    @Value("${meida.fileUrl:''}")
    private String fileUrl;

    @Resource
    EsHandler esHandler;

    @Override
    public ResultBody beforeAdd(CriteriaSave cs, ArcOriginal original, EntityMap extra) {
        return ResultBody.ok();
    }

    @Override
    public ResultBody beforeEdit(CriteriaUpdate<ArcOriginal> cu, ArcOriginal t, EntityMap extra) {
        ApiAssert.isNotEmpty("修改原文不能为空", t);
        ApiAssert.isNotEmpty("修改原文id不能为空", t.getArcOriginalId());
        ApiAssert.isNotEmpty("门类id不能为空", t.getCategoryId());
        ApiAssert.isNotEmpty("原文注释不能为空", t.getFileNote());
        cu.lambda().eq(ArcOriginal::getCategoryId, t.getCategoryId());
        return ResultBody.ok();
    }


    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<ArcOriginal> cq, ArcOriginal original, EntityMap requestMap) {
        ApiAssert.isNotEmpty("查询条件不能为空", original);
        ApiAssert.isNotEmpty("档案ID不能为空", original.getArcInfoId());
        ApiAssert.isNotEmpty("门类ID不能为空", original.getCategoryId());
        cq.lambda().eq(ArcOriginal::getCategoryId, original.getCategoryId())
                .eq(ArcOriginal::getArcInfoId, original.getArcInfoId());
        cq.orderByAsc("original.seq");
        cq.orderByDesc("original.createTime");
        return ResultBody.ok();
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public ResultBody beforeListEntityMap(CriteriaQuery<ArcOriginal> cq, ArcOriginal original, EntityMap requestMap) {
        ApiAssert.isNotEmpty("查询条件不能为空", original);
        ApiAssert.isNotEmpty("档案ID不能为空", original.getArcInfoId());
        ApiAssert.isNotEmpty("门类ID不能为空", original.getCategoryId());
        cq.lambda().eq(ArcOriginal::getCategoryId, original.getCategoryId())
                .eq(ArcOriginal::getArcInfoId, original.getArcInfoId());
        cq.orderByAsc("original.seq");
        cq.orderByDesc("original.createTime");
        return ResultBody.ok();
    }

    @Override
    public void srcArcOriginal2TargetArcOriginal(List<Long> arcInfoIds, ArcConfig arcConfig) {
        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<ArcOriginal>();
        queryWrapper.lambda().in(ArcOriginal::getArcInfoId, arcInfoIds)
                .eq(ArcOriginal::getCategoryId, arcConfig.getSrcCategoryId());
        List<ArcOriginal> srcArcOriginals = this.list(queryWrapper);
        List<ArcOriginal> targetArcOriginals = srcArcOriginals.stream().map(item -> {
            item.setCategoryId(arcConfig.getTargetCategoryId());
            //TODO 需要更新搜索引擎 原文数据对应的门类ID
            item.setIndexStatus(ArchiveEnumInteger.IS_FALSE.getCode());
            return item;
        }).collect(Collectors.toList());

        this.saveBatch(targetArcOriginals);
        this.remove(queryWrapper);
        //TODO 更新全文索引
    }

    @Override
    public void delOriginal(List<Long> arcInfoIds, Long categoryId) {

        //    删除物理文件
        List<ArcOriginal> list = listByArcInfoIds(arcInfoIds, categoryId);
        //TODO 删除全文索引
        esHandler.delEs(list);
        delOriginalOss(list);
        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<ArcOriginal>();
        queryWrapper.lambda().in(ArcOriginal::getArcInfoId, arcInfoIds)
                .eq(ArcOriginal::getCategoryId, categoryId);

        this.remove(queryWrapper);

    }

    //    删除物理文件
    private void delOriginalOss(List<ArcOriginal> list) {
        if (FlymeUtils.isNotEmpty(list)) {
            List<String> objects = new ArrayList<>();
            OssSetting ossSetting = mioClient.getOssSetting();
            for (ArcOriginal arcOriginal : list) {
                String localPath = arcOriginal.getLocalPath();
                if (FlymeUtils.isNotEmpty(localPath)) {
                    objects.add(localPath.replace(ossSetting.getFilePath() + "/archive/", ""));
                }
            }
            syncService.removeOriginalOss(objects);
        }
    }


    /**
     * 回收站清空原文
     *
     * @param categoryId
     * @param status     为null不过滤  0预归档-文件级 1预归档-档案级
     */
    @Override
    public void clearOriginal(Long categoryId, Integer status) {
        //清空原文只能清空回收站原文
        QueryWrapper<ArcInfo> arcInfoQueryWrapper = new QueryWrapper<ArcInfo>();
        arcInfoQueryWrapper.lambda().eq(ArcInfo::getIsRecycle, ArchiveEnumInteger.IS_TRUE.getCode())
                .eq(ArcInfo::getCategoryId, categoryId)
                .select(ArcInfo::getArcInfoId);
        if (FlymeUtils.isNotEmpty(status)) {
            arcInfoQueryWrapper.lambda().eq(ArcInfo::getStatus, status);
        }
        List<ArcInfo> list = this.arcInfoService.list(arcInfoQueryWrapper);
        if (FlymeUtils.isNotEmpty(list)) {


            List<Long> arcInfoIds = list.stream().map(item -> item.getArcInfoId()).collect(Collectors.toList());
            List<ArcOriginal> lists = listByArcInfoIds(arcInfoIds, categoryId);
            //TODO 删除全文索引

            esHandler.delEs(lists);

            QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<ArcOriginal>();
            queryWrapper.lambda().eq(ArcOriginal::getCategoryId, categoryId)
                    .in(ArcOriginal::getArcInfoId, arcInfoIds);


            this.remove(queryWrapper);
        }
    }

    @Override
    public ResultBody removeOriginal(Map param) {
        EntityMap map = new EntityMap(param);
        Long categoryId = map.getLong("categoryId");
        String arcInfoIds = map.get("arcInfoIds");
        Long arcInfoId = map.getLong("arcInfoId");
        String originalIds = map.get("originalIds");
        ApiAssert.isNotEmpty("门类id不能为空", categoryId);
        ApiAssert.anyOneIsNotNull("档案id与原文id不能同时为空", arcInfoIds, originalIds);
        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<ArcOriginal>();
        queryWrapper.lambda().eq(ArcOriginal::getCategoryId, Long.parseLong(categoryId.toString()));
        if (FlymeUtils.isNotEmpty(originalIds)) {
            String[] originalIdsArr = originalIds.split(",");
            queryWrapper.lambda().in(ArcOriginal::getArcOriginalId, Arrays.stream(originalIdsArr).map(item -> Long.parseLong(item)).collect(Collectors.toList()));
            //更新原文数量
            if (FlymeUtils.allNotNull(categoryId, arcInfoId)) {
                //arcInfoService.updateOriginalCount(categoryId.toString(), arcInfoId.toString(), originalIdsArr.length * -1);
            }

        } else {
            String[] arcInfoIdsArr = arcInfoIds.split(",");
            queryWrapper.lambda().in(ArcOriginal::getArcInfoId, Arrays.stream(arcInfoIdsArr).map(item -> Long.parseLong(item)).collect(Collectors.toList()));
            //更新原文数量
            if (FlymeUtils.isNotEmpty(arcInfoIdsArr)) {
                for (String id : arcInfoIdsArr) {
                    arcInfoService.updateOriginalCount(categoryId.toString(), id.toString());
                    List<Long> ids = selectIddByArcInfoId(categoryId, Long.parseLong(id));
                    if (FlymeUtils.isNotEmpty(ids)) {
                        //删除原文索引
                        deleteOriginal(StringUtils.join(ids, ","));
                    }
                }
            }
        }
        //待删除原文物理文件
        List<ArcOriginal> list = list(queryWrapper);
        this.remove(queryWrapper);

        if (FlymeUtils.isNotEmpty(originalIds)) {
            //删除原文索引
            deleteOriginal(originalIds);
        }
        //删除原文文件
        delOriginalOss(list);
        if (FlymeUtils.allNotNull(categoryId, arcInfoId)) {
            int count = (int) this.count(new QueryWrapper<ArcOriginal>().lambda().eq(ArcOriginal::getCategoryId, Long.parseLong(categoryId.toString())).eq(ArcOriginal::getArcInfoId, arcInfoId));
            arcInfoService.updateOriginalCount(categoryId.toString(), arcInfoId.toString());
            arcInfoService.updateOriginalCount(categoryId.toString(), arcInfoId.toString(), count);

        }
        return ResultBody.ok();
    }

    @Override
    public EntityMap upload(HttpServletRequest request, MultipartFile[] file, Long[] fileIds, Long categoryId, Long busId, String busType) {

        busId = categoryId != null ? categoryId : busId;
        return sysFileService.upload(request, file, fileIds, busId, busType, "originalUploadHandler");
    }

    @Override
    public List<Long> selectIddByArcInfoId(Long categoryId, Long arcInfoId) {
        CriteriaQuery cq = new CriteriaQuery(ArcOriginal.class);
        cq.select("arcOriginalId");
        cq.eq(true, "arcInfoId", arcInfoId);
        cq.eq(true, "categoryId", categoryId);
        return listObjs(cq, e -> new Long(e.toString()));
    }


    /**
     * 删除原文全文索引
     *
     * @param originalIds
     */
    private void deleteOriginal(String originalIds) {
        if (FlymeUtils.isNotEmpty(originalIds)) {

            List<Long> ids = Arrays.stream(StrUtil.splitToArray(originalIds, ','))
                    .map(Long::parseLong)
                    .collect(Collectors.toList());
            //删除全文索引
            esHandler.delEsByIds(ids);

            //arcOriginalRepository.deleteById(Long.parseLong(originalId));

        }
    }

    /**
     * 批量挂接
     */
    @Override
    public ResultBody batchHookUp(Long categoryId) {
        String userName = OpenHelper.getUserName();
        Long userId = OpenHelper.getUserId();
        List<ArcOriginal> list = new ArrayList<>();
        ApiAssert.isNotEmpty("categoryId不能为空", categoryId);
        List<MinioLog> fileList = minioLogService.selectByUserName(userName, null);
        OssSetting ossSetting = mioClient.getOssSetting();
        if (FlymeUtils.isNotEmpty(fileList)) {
            for (MinioLog minioLog : fileList) {
                String filePath = minioLog.getKeyName();
                String value = minioLog.getValue();
                Long minioId = minioLog.getId();
                JSONObject result = JSONObject.parseObject(value);
                if (FlymeUtils.isNotEmpty(result)) {
                    JSONArray records = result.getJSONArray("Records");
                    JSONObject record = records.getJSONObject(0);
                    JSONObject s3 = record.getJSONObject("s3");
                    JSONObject responseElements = record.getJSONObject("responseElements");
                    //OSS父路径
                    String ossBasePath = responseElements.getString("x-minio-origin-endpoint");
                    JSONObject object = s3.getJSONObject("object");
                    //文件类型
                    String contentType = object.getString("contentType");
                    //文件名称
                    String fileName = object.getString("key");
                    try {
                        String decodeStr = URLDecoder.decode(fileName, "UTF-8");
                        fileName = decodeStr.substring(decodeStr.lastIndexOf("/") + 1);
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    //文件大小(单位字节)
                    Long fileSize = object.getLong("size");
                    //根据文件路径分析档案
                    String arcNo = getArcNo(filePath);
                    System.out.println("挂接路径#################################:" + arcNo);
                    if (FlymeUtils.isNotEmpty(arcNo)) {
                        ArcInfo arcInfo = getArcInfo(arcNo, categoryId);
                        if (FlymeUtils.isNotEmpty(arcInfo)) {
                            String localPath = ossSetting.getFilePath() + "/" + filePath;
                            ArcOriginal arcOriginal = new ArcOriginal();
                            arcOriginal.setArcInfoId(arcInfo.getArcInfoId());
                            arcOriginal.setCategoryId(categoryId);
                            arcOriginal.setQzId(arcInfo.getQzId());
                            arcOriginal.setFileType(FileUploadUtil.getExtend(fileName));
                            arcOriginal.setFileContenttype(contentType);
                            arcOriginal.setFileSize(fileSize);
                            arcOriginal.setFileName(fileName);
                            arcOriginal.setOssPath(mioClient.getBasePath() + filePath);
                            arcOriginal.setLocalPath(localPath);
                            save(arcOriginal);
                            try {
                                arcInfoService.updateOriginalCount(categoryId.toString(), arcInfo.getArcInfoId().toString(), 1);
                                //更新minioLog状态
                                minioLogService.updateStatus(minioId);
                                //发送挂接通知
                                //sendMessage(userId, fileName);
                                //保存全文索引//TODO 暂时屏蔽
                                esHandler.saveEs(arcOriginal);

                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
        return ResultBody.ok();
    }

    /**
     * 批量挂接前检测
     */
    @Override
    public ResultBody checkHookUp() {
        EntityMap result = new EntityMap();
        //是否禁用文件名挂接
        Boolean tag1 = false;
        //是否禁用文件夹挂接
        Boolean tag2 = false;
        //是否禁用嵌套文件夹挂接
        Boolean tag3 = false;
        String userName = OpenHelper.getUserName();
        //判断是否是微服务
        Object object = applicationContext.getEnvironment().getProperty(CommonConstants.CLOUD_SERVER_KEY);
        if (FlymeUtils.isEmpty(object)) {
            //单机版使用固定目录
            userName = "未挂接";
            //创建目录
            String filePath = mioClient.getOssSetting().getFilePath() + "/archive/" + userName;
            FileUtil.mkdir(filePath);
            String filePath2 = mioClient.getOssSetting().getFilePath() + "/archive/" + "已挂接";
            FileUtil.mkdir(filePath2);
        }
        List<Item> fileList = mioClient.listObjects(userName + "/", false);
        if (FlymeUtils.isNotEmpty(fileList)) {
            String finalUserName = userName + "/";
            //文件名 1层
            tag1 = fileList.stream().filter(i -> !i.isDir() && !i.objectName().equals(finalUserName)).findAny().isPresent();
            // 文件夹 2层
            List<Item> folder = fileList.stream().filter(i -> i.isDir() && !i.objectName().equals(finalUserName)).collect(Collectors.toList());
            for (Item item : folder) {
                List<Item> childList = mioClient.listObjects(item.objectName(), false);
                tag2 = childList.stream().filter(i -> !i.objectName().endsWith("/")).findAny().isPresent();
                if (tag2) {
                    break;
                }
            }
            //多级文件夹是3层级3层以上
            for (Item item : folder) {
                List<Item> files = mioClient.listObjects(item.objectName(), true);
                tag3 = files.stream().filter(i -> !i.objectName().endsWith("/") && StrUtil.split(i.objectName(), '/').size() > 3).findAny().isPresent();
                if (tag3) {
                    break;
                }
            }
          /*  for (Item item : folder) {
                List<Item> childList2 = mioClient.listObjects(item.objectName(), false);
                List<Item> childList3 = childList2.stream().filter(i -> i.objectName().endsWith("/")).collect(Collectors.toList());
                String path=CollUtil.isNotEmpty(childList3)? mioClient.getOssSetting().getFilePath() + "/archive/":"";
                for (Item item31 : childList3) {
                    tag3=showFiles(path+item31.objectName());
                    if(tag3){
                        break;
                    }
                }
            }*/
        }
        result.put("tag1", tag1);
        result.put("tag2", tag2);
        result.put("tag3", tag3);
        return ResultBody.ok(result);
    }

    public static boolean showFiles(String path) {
        File fl = new File(path);
        // 判断path是否为文件夹
        if (fl.isDirectory()) {
            // 若path是文件夹则通过递归遍历输出文件路径
            File[] files = fl.listFiles();
            /*
             * 防止对于某些文件夹，因为用户没有访问权限而导致 java.lang.NullPointerException错误
             * ,所以首先需判断文件夹是否为空,然后再进行递归遍历
             */
            if (files != null) {
                for (File file : files) {
                    showFiles(file.getPath());
                }
            }
        } else {
            return true;
        }
        return false;
    }


    /**
     * 批量挂接
     */
    @Override
    public ResultBody batchHookUp2(Long categoryId, Integer hookUpType) {
        String userName = OpenHelper.getUserName();
        Long userId = OpenHelper.getUserId();
        List<ArcOriginal> list = new ArrayList<>();
        ApiAssert.isNotEmpty("categoryId不能为空", categoryId);
        ArcCategory category = arcCategoryService.getById(categoryId);
        OssSetting ossSetting = mioClient.getOssSetting();
        String bucketName = ossSetting.getBucket();
        String categoryName = category.getCnName();
        sendMessage(userId, categoryName);
        boolean recursive = false;
        if (hookUpType.equals(3)) {
            //是否嵌套读取
            recursive = true;
        }

        EntityMap result = new EntityMap();
        //判断是否是微服务
        Object object = applicationContext.getEnvironment().getProperty(CommonConstants.CLOUD_SERVER_KEY);
        if (FlymeUtils.isEmpty(object)) {
            //单机版使用固定目录
            userName = "未挂接";
        }
        List<Item> fileList = mioClient.listObjects(userName + "/", recursive);
        if (FlymeUtils.isNotEmpty(fileList)) {
            List<Item> files = new ArrayList<>();
            if (hookUpType.equals(1)) {
                for (Item item : fileList) {
                    if (!item.isDir()) {
                        files.add(item);
                    }
                }
            }
            if (hookUpType.equals(2)) {
                for (Item parent : fileList) {
                    if (parent.isDir()) {
                        String parentName = parent.objectName();
                        List<Item> childList = mioClient.listObjects(parentName, false);
                        if (FlymeUtils.isNotEmpty(childList)) {
                            for (Item item : childList) {
                                if (!item.isDir() && !item.objectName().endsWith("/")) {
                                    files.add(item);
                                }
                            }
                        }
                    }
                }
            }
            if (hookUpType.equals(3)) {
                for (Item item : fileList) {
                    if (!item.isDir()) {
                        List<String> split = StrUtil.split(item.objectName(), '/');
                        if (CollUtil.isNotEmpty(split) && split.size() > 3 && !item.objectName().endsWith("/")) {
                            files.add(item);
                        }
                    }
                }
            }
            result.put("filesCount", files.size());
            result.put("categoryName", categoryName);
            hookUpHanlder.hookUpSubmit(files, hookUpType, userId, categoryId, ossSetting, categoryName);
        }
        return ResultBody.ok(result);
    }

    //挂接发送等待通知
    private void sendMessage(Long userId, String categoryName) {
        Map map = new HashMap(5);
        map.put("successCount", 0);
        map.put("failCount", 0);
        map.put("fileName", categoryName);
        map.put("percentage", 0);
        map.put("fileIndex", 0);
        map.put("fileTotal", 0);
        map.put("categoryName", categoryName);
        map.put("surplusFileCount", 0);
        map.put("hookUp", 1);
        map.put("finish", 0);
        map.put("operateType", "wait");

        webSocketMsgService.sendMessage(userId, 3, map);
    }

    /**
     * 根据文件路径分析档案
     *
     * @param filePath
     * @return
     */
    private String getArcNo(String filePath) {
        String arcNo = "";
        if (FlymeUtils.isNotEmpty(filePath)) {
            filePath = filePath.replace("archive/", "");
            filePath = filePath.substring(filePath.indexOf("/") + 1, filePath.lastIndexOf("/"));
            arcNo = filePath.replaceAll("/", "");
        }
        return arcNo;
    }


    @Override
    public List<ArcOriginal> listByArcInfoIds(List<Long> arcInfoIds, Long categoryId) {
        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<ArcOriginal>();
        queryWrapper.lambda().in(ArcOriginal::getArcInfoId, arcInfoIds)
                .eq(ArcOriginal::getCategoryId, categoryId);
        return list(queryWrapper);
    }


    private ArcInfo getArcInfo(String arcNo, Long categoryId) {
        ArcField arcField = arcFieldService.getArcField(categoryId);
        ArcInfo arcInfo = null;
        if (FlymeUtils.isNotEmpty(arcField)) {
            arcInfo = arcInfoService.getArcInfoByField(arcField, null, arcNo, categoryId, true);
            System.out.println("自定义挂接################################" + arcNo);
        } else {
            arcInfo = arcInfoService.getArcInfoByArcNoAndCateGoryId(arcNo, categoryId);
        }
        return arcInfo;
    }

    @Override
    public ResultBody updateArcOriginalInfo(Map params) {
        CriteriaUpdate<ArcOriginal> up = new CriteriaUpdate<>();
        ApiAssert.isNotEmpty("arcOriginalId不能为空", params.get("arcOriginalId"));
        up.lambda().eq(ArcOriginal::getArcOriginalId, Long.valueOf(params.get("arcOriginalId").toString()));
        up.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
        up.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));

        if (null != params.get("fileName")) {
            up.set("fileName", params.get("fileName"));
        }
        if (null != params.get("seq")) {
            up.set("seq", params.get("seq"));
        }
        return ResultBody.ok(update(up));
    }

   /* @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBody upOrDown(Map params) {

        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<>();
        ApiAssert.isNotEmpty("arcOriginalId不能为空", params.get("arcOriginalId"));
        queryWrapper.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
        queryWrapper.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));
        queryWrapper.orderByAsc("seq");
        queryWrapper.orderByDesc("createTime");
        //  拖动角标来源不能为空
        Object fromIndex = params.get("fromIndex");
        //拖动角标目标不能为空
        Object toIndex = params.get("toIndex");
        int fromIndexInt = Integer.parseInt(fromIndex.toString());
        int toIndexInt = Integer.parseInt(toIndex.toString());
        queryWrapper.last(" limit 0 ,"+(fromIndexInt+1));
        List<ArcOriginal> list = this.list(queryWrapper);
        if (fromIndexInt == toIndexInt) {
            ApiAssert.failure("移动前后角标不能相等");
        }
        if (fromIndexInt >= list.size() || fromIndexInt < 0 || toIndexInt >= list.size() || toIndexInt < 0) {
            ApiAssert.failure("移动前后角标不能越界");
        }
        List<ArcOriginal> updateObj = new ArrayList<>();
        queryWrapper.clear();
        queryWrapper.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
        queryWrapper.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));
        queryWrapper.lambda().eq(ArcOriginal::getArcOriginalId, Long.valueOf(params.get("arcOriginalId").toString()));
        ArcOriginal one = getOne(queryWrapper);
        one.setSeq(toIndexInt);
        updateObj.add(one);
        if (fromIndexInt < toIndexInt) {//下移
            for (int i = fromIndexInt + 1; i <= toIndexInt; i++) {
                ArcOriginal obj = new ArcOriginal();
                obj.setArcOriginalId(list.get(i).getArcOriginalId());
                obj.setCategoryId(list.get(i).getCategoryId());
                obj.setArcInfoId(list.get(i).getArcInfoId());
                obj.setSeq(i - 1);
                updateObj.add(obj);
            }
        } else {//上移
            for (int i = toIndexInt; i < fromIndexInt; i++) {
                ArcOriginal obj = new ArcOriginal();
                obj.setArcOriginalId(list.get(i).getArcOriginalId());
                obj.setCategoryId(list.get(i).getCategoryId());
                obj.setArcInfoId(list.get(i).getArcInfoId());
                obj.setSeq(i + 1);
                updateObj.add(obj);
            }
        }
        if (CollUtil.isNotEmpty(updateObj)) {

            for (ArcOriginal arcOriginal : updateObj) {
                CriteriaUpdate<ArcOriginal> up = new CriteriaUpdate<>();
                up.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
                up.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));
                up.lambda().eq(ArcOriginal::getArcOriginalId, arcOriginal.getArcOriginalId());
                up.lambda().set(ArcOriginal::getSeq, arcOriginal.getSeq());
                this.update(up);
            }
        }
        //this.updateBatchById(updateObj);
        return ResultBody.ok();
    }*/

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBody upOrDown(Map params) {
        ApiAssert.isNotEmpty("arcInfoId不能为空", params.get("arcInfoId"));
        ApiAssert.isNotEmpty("arcOriginalId不能为空", params.get("arcOriginalId"));
        String arcOriginalId = params.get("arcOriginalId").toString();
        List<String> split = StrUtil.split(arcOriginalId, ',');
        for (int i = 0; i < split.size(); i++) {
            CriteriaUpdate<ArcOriginal> up = new CriteriaUpdate<>();
            up.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
            up.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));
            up.lambda().eq(ArcOriginal::getArcOriginalId, split.get(i));
            up.lambda().set(ArcOriginal::getSeq, i);
            update(up);
        }
        return ResultBody.ok();
    }

    @Autowired
    private OpenCommonProperties openCommonProperties;


    @Override
    public ResultBody convertArcOriginal(HttpServletRequest request, Map params) {
        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<>();
        ApiAssert.isNotEmpty("arcInfoId不能为空", params.get("arcInfoId"));
        ApiAssert.isNotEmpty("type不能为空", params.get("type"));
        ApiAssert.isNotEmpty("fileType", params.get("fileType"));
        queryWrapper.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
        queryWrapper.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));
        try {
            String target = "";
            String odfTarget = "";
            String type = params.get("type").toString();
            String fileType = params.get("fileType").toString();
            List<String> arcOriginalIds = StrUtil.split(params.get("arcOriginalId").toString(), ',');
            queryWrapper.lambda().in(StrUtil.isNotEmpty(params.get("arcOriginalId").toString()), ArcOriginal::getArcOriginalId, arcOriginalIds);
            List<ArcOriginal> list = list(queryWrapper);

            switch (fileType) {
                case "pdf":
                    if (true) {
                        //if ("1".equals(type)) {
                        String suffix = arcOriginalIds.size() > 1 ? "原文合并文件.pdf" : list.get(0).getFileName().split("\\.")[0] + "-转换.pdf";
                        List<String> imgs = new ArrayList<>();
                        List<File> files = new ArrayList<>();
                        target = uploadFolder + IdWorker.getIdStr() + suffix;

                        for (ArcOriginal arcOriginal : list) {
                            String tmp = uploadFolder + arcOriginal.getFileName();
                            HttpUtil.downloadFile(arcOriginal.getOssPath(), tmp);
                            if (arcOriginal.getFileContenttype().indexOf("image") > -1) {
                                imgs.add(tmp);
                            } else {
                                File srcFile = new File(tmp);
                                File targetDir = new File(srcFile.getParentFile(), "pdf");
                                FileConvertUtil.wordToPdf(tmp, targetDir.getAbsolutePath());
                                files.add(targetDir);

                               /* ConvertResult convertResult = OfficeUtils.convertPdf(srcFile, targetDir, openCommonProperties.getOfficePath());
                                if (convertResult.isSuccess()) {
                                    FileUtil.del(tmp);
                                    files.add(new File(convertResult.getTargetFile()));
                                }*/
                            }
                        }
                        if (CollUtil.isNotEmpty(imgs)) {
                            manyImageToOnePdf(imgs, target);
                            imgs.forEach(i -> FileUtil.del(i));
                        }
                        if (CollUtil.isNotEmpty(files)) {
                            mulFile2One(files, target);
                            files.forEach(i -> FileUtil.del(i));
                        }

                    } else {

                    }
                    break;
                case "ofd":
                    if (true) {
                        //if ("1".equals(type)) {
                        String suffix = arcOriginalIds.size() > 1 ? "原文合并文件.ofd" : list.get(0).getFileName().split("\\.")[0] + "-转换.ofd";
                        List<String> imgs = new ArrayList<>();
                        List<File> files = new ArrayList<>();
                        target = uploadFolder + IdWorker.getIdStr() + ".pdf";

                        for (ArcOriginal arcOriginal : list) {
                            String tmp = uploadFolder + arcOriginal.getFileName();
                            HttpUtil.downloadFile(arcOriginal.getOssPath(), tmp);
                            if (arcOriginal.getFileContenttype().indexOf("image") > -1) {
                                imgs.add(tmp);
                            } else {
                                File srcFile = new File(tmp);
                                File targetDir = new File(srcFile.getParentFile(), "pdf");
                                if (arcOriginal.getFileType().equals("pdf")) {
                                    files.add(srcFile);
                                } else {
                                    /*ConvertResult convertResult = OfficeUtils.convertPdf(srcFile, targetDir, openCommonProperties.getOfficePath());
                                    if (convertResult.isSuccess()) {
                                        files.add(new File(convertResult.getTargetFile()));
                                    }*/
                                    FileConvertUtil.wordToPdf(tmp, targetDir.getAbsolutePath());
                                    files.add(targetDir);

                                }
                            }
                        }
                        if (CollUtil.isNotEmpty(imgs)) {
                            manyImageToOnePdf(imgs, target);
                            imgs.forEach(i -> FileUtil.del(i));
                        }
                        if (CollUtil.isNotEmpty(files)) {
                            mulFile2One(files, target);
                            files.forEach(i -> FileUtil.del(i));
                        }
                        odfTarget = target + "";
                        Path src = Paths.get(target);
                        String ofdPath = uploadFolder + IdWorker.getIdStr() + suffix;
                        Path dst = Paths.get(ofdPath);
                        try (PDFConverter converter = new PDFConverter(dst)) {
                            converter.convert(src);
                            target = ofdPath;
                        }

                    }
                    break;
            }


           /* if ("1".equals(params.get("type").toString())) {
                queryWrapper.lambda().eq(ArcOriginal::getArcOriginalId, Long.valueOf(params.get("arcOriginalId").toString()));
                ArcOriginal one = getOne(queryWrapper);
                String tmp = uploadFolder + one.getFileName();
                HttpUtil.downloadFile(one.getOssPath(), tmp);
                String[] split = tmp.split("\\.");
                if ("pdf".equals(params.get("fileType").toString())) {

                    Path ofdPath = Paths.get(tmp);
                    Path pdfPath = Paths.get(split[0] + "-转换.pdf");
                    try (OFDExporter exporter = new PDFExporterIText(ofdPath, pdfPath)) {
                        exporter.export();
                    }
                    target = split[0] + "-转换.pdf";
                    //target = PdfUtils.ofd2Pdf(tmp, split[0] + "-转换.pdf");

                } else if ("ofd".equals(params.get("fileType").toString())) {

                    Path src = Paths.get(tmp);
                    Path dst = Paths.get(split[0] + "-转换.ofd");
                    try (PDFConverter converter = new PDFConverter(dst)) {
                        converter.convert(src);
                    }
                    target = split[0] + "-转换.ofd";
                    //target = PdfUtils.pdf2Ofd(tmp, split[0] + "-转换.ofd");
                }
            } else {
                queryWrapper.lambda().in(StrUtil.isNotEmpty(params.get("arcOriginalId").toString()), ArcOriginal::getArcOriginalId, StrUtil.split(params.get("arcOriginalId").toString(), ','));
                List<ArcOriginal> list = list(queryWrapper);
                List<String> imgs = new ArrayList<>();
                for (ArcOriginal arcOriginal : list) {
                    String tmp = uploadFolder + arcOriginal.getFileName();
                    HttpUtil.downloadFile(arcOriginal.getOssPath(), tmp);
                    imgs.add(tmp);
                }
                if ("pdf".equals(params.get("fileType").toString())) {
                    target = uploadFolder + IdWorker.getIdStr() + "原文合并文件.pdf";
                    PdfUtils.manyImageToOnePdf(imgs, target);
                } else if ("ofd".equals(params.get("fileType").toString())) {
                }
                imgs.forEach(i -> FileUtil.del(i));
            }*/

            if (StrUtil.isNotEmpty(target)) {
                log.debug(target);
                File file = new File(target);
                FileInputStream input = new FileInputStream(file);
                //重命名文件
                String fileKey = FileUploadUtil.datePath() + "/" + FlymeUtils.renameFile(file.getName());
                String contentType = MediaTypeFactory.getMediaType(file.getName()).orElse(MediaType.APPLICATION_OCTET_STREAM).toString();
                MultipartFile targetFiles = new MockMultipartFile(file.getName(), fileKey, contentType, IOUtils.toByteArray(input));
                mioClient.upload(targetFiles);
                FileUtil.del(file);
                String odfKey = "";
                if (StrUtil.isNotEmpty(odfTarget)) {
                    File file1 = new File(odfTarget);
                    FileInputStream input1 = new FileInputStream(file1);
                    odfKey = FileUploadUtil.datePath() + "/" + FlymeUtils.renameFile(file1.getName());
                    MultipartFile targetFiles1 = new MockMultipartFile(file1.getName(), odfKey, contentType, IOUtils.toByteArray(input1));
                    mioClient.upload(targetFiles1);
                    FileUtil.del(file1);
                }

                hookUpHanlder.insertArcInfo(null, Long.valueOf(params.get("categoryId").toString()), arcInfoService.getArcInfo(Long.valueOf(params.get("arcInfoId").toString()), Long.valueOf(params.get("categoryId").toString())), file.getName().substring(19), file.length(), odfKey, fileKey, mioClient.getOssSetting());

            }
            return ResultBody.ok();

        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return ResultBody.failed();

    }

    /**
     * 多个图片合成一个pdf
     */
    public static void manyImageToOnePdf(List<String> imgages, String target) throws IOException {
        PDDocument doc = new PDDocument();
        //创建一个空的pdf文件
        doc.save(target);

        PDPage page;
        PDImageXObject pdImage;
        PDPageContentStream contents;
        BufferedImage bufferedImage;
        String fileName;
        float w, h;
        File tempFile;
        int index;

        for (int i = 0; i < imgages.size(); i++) {
            tempFile = new File(imgages.get(i));
            fileName = tempFile.getName();
            index = fileName.lastIndexOf(".");
            if (index == -1) {
                continue;
            }
            bufferedImage = ImageIO.read(tempFile);
            //Retrieving the page
            pdImage = LosslessFactory.createFromImage(doc, bufferedImage);
            w = pdImage.getWidth();
            h = pdImage.getHeight();


            page = new PDPage(new PDRectangle(w, h));
            //page = new PDPage();
            contents = new PDPageContentStream(doc, page);

            //插入图片,图片太大按scale比例缩小
            float pageWidth = page.getMediaBox().getWidth();
            float pageHeight = page.getMediaBox().getHeight();
            int imageHeight = pdImage.getHeight();
            int imageWidth = pdImage.getWidth();
            float scale = pageWidth / imageWidth;
            scale = Math.min(1, scale);
            if (pageHeight < imageHeight) {

                contents.drawImage(pdImage, (pageWidth - imageWidth * scale) / 2, (pageHeight - imageHeight * scale) / 2, imageWidth * scale, imageHeight * scale);
            } else {
                contents.drawImage(pdImage, 0, 0, imageWidth * scale, pageHeight);

            }

            //contents.drawImage(pdImage, 0, 0, w, h);
            contents.close();
            doc.addPage(page);
        }
        //保存pdf
        doc.save(target);
        //关闭pdf
        doc.close();
    }

    /**
     * description: pdf合并工具类
     * date: 2023年-05月-16日 16:01
     * author: ldd
     *
     * @param files
     * @param targetPath
     * @return java.io.File
     */
    public static File mulFile2One(List<File> files, String targetPath) throws Exception {
        PDFMergerUtility mergePdf = new PDFMergerUtility();
        for (File f : files) {
            if (f.exists() && f.isFile()) {
                // 循环添加要合并的pdf
                mergePdf.addSource(f);
            }
        }
        // 设置合并生成pdf文件名称
        mergePdf.setDestinationFileName(targetPath);
        // 合并pdf
        mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
        return new File(targetPath);
    }


    @Override
    public void downloadArcOriginal(HttpServletRequest request, HttpServletResponse response, Map params, SysFile sysFile, Boolean sync) {
        ApiAssert.isNotEmpty("原文ID不能为空", params.get("arcOriginalId"));
        ApiAssert.isNotEmpty("categoryId不能为空", params.get("categoryId"));
        ApiAssert.isNotEmpty("arcInfoId不能为空", params.get("arcInfoId"));

        Object obj = redisUtils.get(ArchiveConstants.REDIS_SETTING_KEY_PREFIX);
        Map objMap = (Map) obj;
        String customExpand = MapUtil.getStr(objMap, "customExpand");
        ArcWaterMarkJson arcWaterMarkJson = JSONObject.parseObject(customExpand, ArcWaterMarkJson.class);
        //下载是否加水印
        boolean downloadWaterMark = arcWaterMarkJson.getOriginal().contains(params.get("type"));

        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
        queryWrapper.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));
        List<String> arcOriginalIds = StrUtil.split(params.get("arcOriginalId").toString(), ',');
        queryWrapper.lambda().in(ArcOriginal::getArcOriginalId, arcOriginalIds);
        List<ArcOriginal> list = list(queryWrapper);
        compressedPackageExport(request, response, list, downloadWaterMark, arcWaterMarkJson, sysFile, sync);
    }

    @Override
    public void downloadCheckCount(Long fileId) {
        SysFile sysFile = sysFileService.getById(fileId);
        if (FlymeUtils.isNotEmpty(sysFile)) {
            Integer downloadCount = FlymeUtils.getInteger(sysFile.getDownloadCount(), 0);
            if (downloadCount >= 1) {
                ApiAssert.failure("请勿重复下载");
            }
            CriteriaUpdate cu = new CriteriaUpdate();
            cu.set("downloadCount", downloadCount + 1);
            cu.eq("fileId", fileId);
            sysFileService.update(cu);
        }
    }

    @Override
    public void
    clearDownLoad(Long fileId) {
        Long userId = OpenHelper.getUserId();
        CriteriaDelete cd = new CriteriaDelete();
        cd.eq("createUser", userId);
        cd.gt("downloadCount", 0);
        if (FlymeUtils.isNotEmpty(fileId)) {
            cd.eq("fileId", fileId);
        }
        List<SysFile> list = sysFileService.list(new QueryWrapper<SysFile>().eq(FlymeUtils.isNotEmpty(fileId), "fileId", fileId).gt("downloadCount", 0).eq("createUser", userId));
        for (SysFile sysFile : list) {
            mioClient.removeObject(sysFile.getOssPath().replace(mioClient.getBaseOssPath(), ""));
            //sysFileService.removeById(sysFile);
        }
        sysFileService.remove(cd);

    }

    /**
     * @param response           http servlet响应
     * @param httpServletRequest http servlet请求
     */
    @SneakyThrows
    public void compressedPackageExport(HttpServletRequest httpServletRequest, HttpServletResponse response, List<ArcOriginal> list, boolean downloadWaterMark, ArcWaterMarkJson arcWaterMarkJson, SysFile sysFile, Boolean sync) {

        String type = httpServletRequest.getParameter("type");
        // 压缩包名称
        String zipName = IdWorker.getIdStr() + ".zip";
        //异步导出时不设置响应头
        if (!sync) {
            //设置响应头信息
            response.reset();
            response.setCharacterEncoding("utf-8");
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(zipName, "UTF-8") + "\"");
        }
        // 获取临时目录
        String tempDir = uploadFolder + IdWorker.getIdStr() + "/";
        FileUtil.mkdir(tempDir);
        //设置压缩流：直接写入response，实现边压缩边下载
        ZipOutputStream zipOs = null;
        //循环将文件写入压缩流
        DataOutputStream os = null;
        //文件
        File file = null;
        String waterMarkPlus = "";

        try {
            File zipFile = new File(tempDir + zipName);
            if (!sync) {
                zipOs = new ZipOutputStream(new BufferedOutputStream(response.getOutputStream()));
            } else {
                zipOs = new ZipOutputStream(new FileOutputStream(zipFile));
            }
            //设置压缩方法
            zipOs.setMethod(ZipOutputStream.DEFLATED);

            //遍历文件信息（主要获取文件名/文件路径等）
            String footer = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日 E HH时mm分ss秒 ") + " ID: " + (StrUtil.isEmpty(OpenHelper.getUserName()) ? sysFile.getCreateUser() : OpenHelper.getUserName());
            boolean footerFlag = "1".equals(arcWaterMarkJson.getFooter());
            for (ArcOriginal t : list) {
                int img = 0, text = 0;
                float fillOpacity = 0;

                if (downloadWaterMark) {
                    fillOpacity = Float.valueOf(arcWaterMarkJson.getTransparent() * 0.01 + "");
                    img = arcWaterMarkJson.getImg();
                    text = arcWaterMarkJson.getText();
                    if (arcWaterMarkJson.getTextContent().uuid == 1) {
                        waterMarkPlus = (StrUtil.isEmpty(OpenHelper.getUserName()) ? sysFile.getCreateUser().toString() : OpenHelper.getUserName());
                    }
                    if (arcWaterMarkJson.getTextContent().date == 1) {
                        waterMarkPlus = DateUtil.formatDateTime(DateUtil.date()).replace("-", "/").replace(":", "/").replace(" ", "/" + DateUtil.thisDayOfWeekEnum().toChinese() + "/");
                    }
                }
                try {
                    //文件名（包含后缀名，如：测试.pdf）
                    String name = t.getFileName();
                    //本地文件路径（绝对路径，包含后缀名，如：F:\\test\\测试.pdf），这里是在windows上测试的，路径是反斜杠
                    String path = tempDir + name;
                    if ("true".equals(standalone)) {
                        path = t.getLocalPath();
                        if (downloadWaterMark && arcWaterMarkJson.getOriginal().contains(type)) {
                            String out = path.split("\\.")[0] + "watermark" + "." + path.split("\\.")[1];
                            if (img == 1 && text == 1) {
                                out = FileWaterMarkUtil.PDFAddTextImgWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, arcWaterMarkJson.getImgContent().imgUrl, footerFlag, footer);
                            } else if (img == 0 && text == 1) {
                                out = FileWaterMarkUtil.PDFAddWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                            } else if (img == 1 && text == 0) {
                                out = FileWaterMarkUtil.PDFAddImgWaterMaker(path, out, arcWaterMarkJson.getImgContent().imgUrl, fillOpacity, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                            } else if (footerFlag && img == 0 && text == 0) {
                                out = FileWaterMarkUtil.PDFAddFooter(out.replace("watermark", ""), out, footer);
                            }
                            if (!footerFlag && img == 0 && text == 0) {
                                out = path;
                            }
                            file = new File(out);
                        } else {
                            file = new File(path);
                        }
                        if (!FileUtil.exist(file)) {
                            throw new RuntimeException("文件不存在");
                        }
                        //添加ZipEntry，并将ZipEntry写入文件流
                        zipOs.putNextEntry(new ZipEntry(name));
                        os = new DataOutputStream(zipOs);
                        FileInputStream fs = new FileInputStream(file);
                        byte[] b = new byte[100];
                        int length;
                        //读入需要下载的文件的内容，打包到zip文件
                        while ((length = fs.read(b)) != -1) {
                            os.write(b, 0, length);
                        }
                        //关闭流
                        fs.close();
                    } else {
                        if (downloadWaterMark && arcWaterMarkJson.getOriginal().contains(type)) {
                            HttpUtil.downloadFile(t.getOssPath(), path);
                            if (t.getFileType().equals("pdf") || t.getFileType().equals("ofd")) {
                                String out = path.split("\\.")[0] + "watermark" + "." + path.split("\\.")[1];
                                if (t.getFileType().equals("pdf")) {
                                    if (img == 1 && text == 1) {
                                        out = FileWaterMarkUtil.PDFAddTextImgWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, arcWaterMarkJson.getImgContent().imgUrl, footerFlag, footer);
                                    } else if (img == 0 && text == 1) {
                                        out = FileWaterMarkUtil.PDFAddWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                                    } else if (img == 1 && text == 0) {
                                        out = FileWaterMarkUtil.PDFAddImgWaterMaker(path, out, arcWaterMarkJson.getImgContent().imgUrl, fillOpacity, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                                    } else if (footerFlag && img == 0 && text == 0) {
                                        out = FileWaterMarkUtil.PDFAddFooter(out.replace("watermark", ""), out, footer);
                                    }
                                    if (!footerFlag && img == 0 && text == 0) {
                                        out = path;
                                    }
                                } else {
                                    if (img == 1 && text == 1) {
                                        out = FileWaterMarkUtil.OFDAddImgAndWatermark(path, out,arcWaterMarkJson.getImgContent().imgUrl, arcWaterMarkJson.getTextContent().value, waterMarkPlus,fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getImgContent().position, arcWaterMarkJson.getTextContent().rotate);
                                    } else if (img == 0 && text == 1) {
                                        out = FileWaterMarkUtil.OFDAddWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus,fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getImgContent().position, arcWaterMarkJson.getTextContent().rotate);
                                    } else if (img == 1 && text == 0) {
                                        out = FileWaterMarkUtil.OFDAddImgWatermark(path, out,arcWaterMarkJson.getImgContent().imgUrl,fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getImgContent().position, arcWaterMarkJson.getTextContent().rotate);
                                    }
                                   /*else if (footerFlag && img == 0 && text == 0) {
                                       out = FileWaterMarkUtil.PDFAddFooter(out.replace("watermark", ""), out, footer);
                                   }
                                   if (!footerFlag && img == 0 && text == 0) {
                                       out = path;
                                   }*/
                                }


                                /*if("1".equals(  arcWaterMarkJson.getFooter())){
                                    FileWaterMarkUtil.PDFAddFooter(out.replace("watermark",""), out, DateUtil.format(DateUtil.date(),"yyyy年MM月dd日 E HH时mm分ss秒 ")+" ID: "+OpenHelper.getUserName() );
                                }*/
                                file = new File(out);
                            } else {
                                file = new File(path);
                            }
                            //添加ZipEntry，并将ZipEntry写入文件流
                            zipOs.putNextEntry(new ZipEntry(name));
                            os = new DataOutputStream(zipOs);
                            FileInputStream fs = new FileInputStream(file);
                            byte[] b = new byte[100];
                            int length;
                            //读入需要下载的文件的内容，打包到zip文件
                            while ((length = fs.read(b)) != -1) {
                                os.write(b, 0, length);
                            }
                            //关闭流
                            fs.close();
                        } else {
                            URL url = new URL(t.getOssPath());
                            URLConnection connection = url.openConnection();
                            InputStream is = connection.getInputStream();
                            //添加ZipEntry，并将ZipEntry写入文件流
                            zipOs.putNextEntry(new ZipEntry(name));
                            os = new DataOutputStream(zipOs);
                            byte[] b = new byte[100];
                            int length;
                            //读入需要下载的文件的内容，打包到zip文件
                            while ((length = is.read(b)) != -1) {
                                os.write(b, 0, length);
                            }
                            is.close();
                        }
                    }


                } catch (Exception e) {
                    e.printStackTrace();
                    log.error("下载文件出错! " + e.getMessage());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (os != null) {
                    os.flush();
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            System.gc();
        }
        if (sync) {
            String bathPath = mioClient.getBaseOssPath();
            Long userId = sysFile.getCreateUser();
            String ossPath = "userfile/" + userId + "/" + zipName;
            //上传文件到minio
            mioClient.uploadByPath(tempDir + zipName, ossPath);
            sysFile.setLocalPath(tempDir + zipName);
            sysFile.setOssPath(bathPath + ossPath);
            //sysFile.setOssPath(fileUrl + tempDir.replace(uploadFolder, "") + zipName);
            sysFileService.updateById(sysFile);
        }

    }


    @Override
    public String printArcOriginal(HttpServletRequest request, HttpServletResponse response, Map params) {
        ApiAssert.isNotEmpty("原文ID不能为空", params.get("arcOriginalId"));
        ApiAssert.isNotEmpty("categoryId不能为空", params.get("categoryId"));
        ApiAssert.isNotEmpty("arcInfoId不能为空", params.get("arcInfoId"));

        Object obj = redisUtils.get(ArchiveConstants.REDIS_SETTING_KEY_PREFIX);
        Map objMap = (Map) obj;
        String customExpand = MapUtil.getStr(objMap, "customExpand");
        ArcWaterMarkJson arcWaterMarkJson = JSONObject.parseObject(customExpand, ArcWaterMarkJson.class);
        //下载是否加水印
        boolean downloadWaterMark = arcWaterMarkJson.getOriginal().contains(params.get("type"));

        QueryWrapper<ArcOriginal> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(ArcOriginal::getCategoryId, Long.valueOf(params.get("categoryId").toString()));
        queryWrapper.lambda().eq(ArcOriginal::getArcInfoId, Long.valueOf(params.get("arcInfoId").toString()));
        queryWrapper.lambda().eq(ArcOriginal::getArcOriginalId, Long.valueOf(params.get("arcOriginalId").toString()));
        ArcOriginal arcOriginal = getOne(queryWrapper);
        //PDF添加水印
        if (downloadWaterMark && "pdf".equals(arcOriginal.getFileType())) {
            String userId = OpenHelper.getStrUserId();
            String footer = DateUtil.format(DateUtil.date(), "yyyy年MM月dd日 E HH时mm分ss秒 ") + " ID: " + userId;
            boolean footerFlag = "1".equals(arcWaterMarkJson.getFooter());

            int img = 0, text = 0;
            float fillOpacity = 0;
            String waterMarkPlus = "";

            fillOpacity = Float.valueOf(arcWaterMarkJson.getTransparent() * 0.01 + "");
            img = arcWaterMarkJson.getImg();
            text = arcWaterMarkJson.getText();
            if (arcWaterMarkJson.getTextContent().uuid == 1) {
                waterMarkPlus = userId;
            }
            if (arcWaterMarkJson.getTextContent().date == 1) {
                waterMarkPlus = DateUtil.formatDateTime(DateUtil.date()).replace("-", "/").replace(":", "/").replace(" ", "/" + DateUtil.thisDayOfWeekEnum().toChinese() + "/");
            }

            String filePath = "";
            try {
                // 获取临时目录
                String tempDir = uploadFolder + IdWorker.getIdStr() + "/";
                FileUtil.mkdir(tempDir);

                //文件名（包含后缀名，如：测试.pdf）
                String name = arcOriginal.getFileName();
                //本地文件路径（绝对路径，包含后缀名，如：F:\\test\\测试.pdf），这里是在windows上测试的，路径是反斜杠
                String path = tempDir + name;
                if (FileUtil.isFile(arcOriginal.getLocalPath())) {
                    path = arcOriginal.getLocalPath();

                    String out = path.split("\\.")[0] + "watermark" + "." + path.split("\\.")[1];
                    if (img == 1 && text == 1) {
                        out = FileWaterMarkUtil.PDFAddTextImgWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, arcWaterMarkJson.getImgContent().imgUrl, footerFlag, footer);
                    } else if (img == 0 && text == 1) {
                        out = FileWaterMarkUtil.PDFAddWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                    } else if (img == 1 && text == 0) {
                        out = FileWaterMarkUtil.PDFAddImgWaterMaker(path, out, arcWaterMarkJson.getImgContent().imgUrl, fillOpacity, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                    } else if (footerFlag && img == 0 && text == 0) {
                        out = FileWaterMarkUtil.PDFAddFooter(out.replace("watermark", ""), out, footer);
                    }
                    if (!footerFlag && img == 0 && text == 0) {
                        out = path;
                    }


                    filePath = out;
                } else {
                    HttpUtil.downloadFile(arcOriginal.getOssPath(), path);
                    if (arcOriginal.getFileType().equals("pdf") || arcOriginal.getFileType().equals("ofd0")) {
                        String out = path.split("\\.")[0] + "watermark" + "." + path.split("\\.")[1];
                        if (img == 1 && text == 1) {
                            out = FileWaterMarkUtil.PDFAddTextImgWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, arcWaterMarkJson.getImgContent().imgUrl, footerFlag, footer);
                        } else if (img == 0 && text == 1) {
                            out = FileWaterMarkUtil.PDFAddWatermark(path, out, arcWaterMarkJson.getTextContent().value, waterMarkPlus, fillOpacity, arcWaterMarkJson.getTextContent().font, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                        } else if (img == 1 && text == 0) {
                            out = FileWaterMarkUtil.PDFAddImgWaterMaker(path, out, arcWaterMarkJson.getImgContent().imgUrl, fillOpacity, arcWaterMarkJson.getTextContent().rotate, footerFlag, footer);
                        } else if (footerFlag && img == 0 && text == 0) {
                            out = FileWaterMarkUtil.PDFAddFooter(out.replace("watermark", ""), out, footer);
                        }
                        if (!footerFlag && img == 0 && text == 0) {
                            out = path;
                        }

                        filePath = out;

                    }


                }

                String bathPath = mioClient.getBaseOssPath();
                String ossPath = "tmp/" + IdWorker.getIdStr() + ".pdf";
                mioClient.uploadByPath(filePath, ossPath);

                return bathPath + ossPath;

            } catch (Exception e) {
                return "";
            }
        }
        return arcOriginal.getOssPath();
    }
}
